package system

import (
	"context"
	"database/sql"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gtime"
	"server/internal/dao"
	"server/internal/model"
	"server/internal/model/do"
	"server/internal/model/entity"
	"server/internal/service"
)

type sSystemPermission struct{}

func init() {
	service.RegisterSystemPermission(&sSystemPermission{})
}

func (s *sSystemPermission) Create(ctx context.Context, in model.SystemPermissionCreateInput) (id int64, err error) {
	if err := s.checkCodeIsRepeat(ctx, in.Code, 0); err != nil {
		return 0, err
	}
	if in.ParentId > 0 {
		if err := s.checkIdIsOk(ctx, in.ParentId); err != nil {
			return 0, gerror.New("ParentId 无效")
		}
	}
	in.CreatedBy = service.SystemLogin().GetAdminID(ctx)
	res, _ := dao.SystemPermission.Ctx(ctx).Insert(in)
	return res.LastInsertId()
}

func (s *sSystemPermission) checkIdIsOk(ctx context.Context, id int64) error {
	if _, err := s.GetOne(ctx, id); err != nil {
		if gerror.Is(err, sql.ErrNoRows) {
			return gerror.New("ParentId 无效") // 数据查询为空时会报错
		}
		return err
	}
	return nil
}

func (s *sSystemPermission) checkCodeIsRepeat(ctx context.Context, code string, id int64) error {
	where := g.Map{
		"code": code,
	}
	if id > 0 {
		where["id <> ?"] = id
	}
	count, err := dao.SystemPermission.Ctx(ctx).Where(where).Count()
	if err != nil {
		return err
	}
	if count > 0 {
		return gerror.New("code 重复")
	}
	return nil //不重复
}

func (s *sSystemPermission) GetOne(ctx context.Context, id int64) (item *entity.SystemPermission, err error) {
	item = new(entity.SystemPermission)
	if id <= 0 {
		return item, nil
	}
	err = dao.SystemPermission.Ctx(ctx).Where(do.SystemPermission{Id: id}).Scan(item)
	return item, err
}

func (s *sSystemPermission) UpdateById(ctx context.Context, id int64, in model.SystemPermissionUpdateInput) (err error) {
	if err := s.checkIdIsOk(ctx, id); err != nil {
		return gerror.New("ID 无效")
	}
	if err := s.checkCodeIsRepeat(ctx, in.Code, id); err != nil {
		return gerror.New("标识符 重复")
	}
	if in.ParentId > 0 {
		if err := s.checkIdIsOk(ctx, in.ParentId); err != nil {
			return gerror.New("上级ID 无效")
		}
	}
	in.UpdatedBy = service.SystemLogin().GetAdminID(ctx)
	_, err = dao.SystemPermission.Ctx(ctx).Where(do.SystemPermission{Id: id}).Update(in)

	if err == nil {
		service.SystemAuthorityCache().SetSystemPermissionLastUpdatedTime(ctx)
	}

	return err
}

func (s *sSystemPermission) DeleteById(ctx context.Context, id int64) (err error) {
	_, err = dao.SystemPermission.Ctx(ctx).Data(do.SystemPermission{
		DeletedAt: gtime.Now(),
		DeletedBy: service.SystemLogin().GetAdminID(ctx),
	}).Where(do.SystemPermission{Id: id}).Update()

	if err == nil {
		service.SystemAuthorityCache().SetSystemPermissionLastUpdatedTime(ctx)
	}

	return err
}

func (s *sSystemPermission) GetTree(ctx context.Context) (interface{}, error) {
	items := make([]model.SystemPermissionTreeItem, 0, 10)
	err := dao.SystemPermission.Ctx(ctx).OrderAsc("type").OrderAsc("sort").Scan(&items)

	tree := s.listToTree(items, 0)
	return tree, err
}

func (s *sSystemPermission) listToTree(items []model.SystemPermissionTreeItem, parentId int64) []model.SystemPermissionTreeItem {
	tree := make([]model.SystemPermissionTreeItem, 0)
	for _, item := range items {
		if item.ParentId == parentId {
			item.Children = s.listToTree(items, item.Id)
			tree = append(tree, item)
		}
	}
	return tree
}
